package br.ufla.pgcc.oomeasures.astvisitors;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;

public class DataAccessMetricVisitor extends ASTVisitor{

	private Map<ModifierKeyword, List<FieldDeclaration>> attributesPerModifier = new HashMap<ModifierKeyword, List<FieldDeclaration>>();
	private double numberOfAttributes;
	
	@SuppressWarnings("unchecked")
	@Override
	public boolean visit(FieldDeclaration field) {
		
		numberOfAttributes++;
		
		List<FieldDeclaration> attributes;
		List<Modifier> modifiers = (List<Modifier>)field.modifiers(); 
		
		for (Object modifier : modifiers) {
			
			if (modifier instanceof Modifier){
			
				attributes = attributesPerModifier.get(((Modifier) modifier).getKeyword()); 
				if (attributes == null) 		
					attributes = new ArrayList<FieldDeclaration>();
				
				attributes.add(field);
				attributesPerModifier.put(((Modifier) modifier).getKeyword(), attributes);
			}
		}				
		
		return super.visit(field);
	}
	
	
	public double calculateDataAccessMetric(){
		
		BigDecimal result = new BigDecimal(0);
		
		double numberOfPrivateAttributes = getPrivateAttributes().size();
		double numberOfProtectedAttributes = getProtectedAttributes().size();
		
		BigDecimal numerator = new BigDecimal(numberOfPrivateAttributes + numberOfProtectedAttributes);
		BigDecimal denominator = new BigDecimal(numberOfAttributes);
		
		if (numberOfAttributes != 0)
			result = numerator.divide(denominator, 3, RoundingMode.UP);
		
		return result.doubleValue();
	}
	
	public List<FieldDeclaration> getAttributesByModifier(ModifierKeyword modifier){
		List<FieldDeclaration> listOfPublicAttributes = attributesPerModifier.get(modifier);
		if (listOfPublicAttributes == null) {
			listOfPublicAttributes = new ArrayList<FieldDeclaration>(0);
		}
		return listOfPublicAttributes;
	}
	
	
	public List<FieldDeclaration> getPrivateAttributes(){
		return getAttributesByModifier(ModifierKeyword.PRIVATE_KEYWORD);
	}
	
	public List<FieldDeclaration> getProtectedAttributes(){
		return getAttributesByModifier(ModifierKeyword.PROTECTED_KEYWORD);
	}
}
